<?php
/**
 * PXML class
 * Class to read XML file based on a standard Pholow syntax.
 * See config.xml file to check how XML file is created
 *
 * @author Patrice Ferlet <metal3d@copix.org> 
 * @package core
 * @license http://opensource.org/licenses/lgpl-3.0.html GNU Lesser General Public License Version 3.0 (LGPLv3)
*/

//based on http://www.php.net/manual/en/function.xml-parse.php#90733
class PXML{
    private $struct;

    function __construct($__url) {
        $xml_values = array();
        $contents = file_get_contents($__url);
        $parser = xml_parser_create('');
        if(!$parser)
        return false;

        xml_parser_set_option($parser, XML_OPTION_TARGET_ENCODING, 'UTF-8');
        xml_parser_set_option($parser, XML_OPTION_CASE_FOLDING, 0);
        xml_parser_set_option($parser, XML_OPTION_SKIP_WHITE, 1);
        xml_parse_into_struct($parser, trim($contents), $xml_values);
        xml_parser_free($parser);
        if (!$xml_values)
        return array();

        $xml_array = array();
        $last_tag_ar =& $xml_array;
        $parents = array();
        $last_counter_in_tag = array(1=>0);
        foreach ($xml_values as $data) {
            switch($data['type']) {
                case 'open':
                    $last_counter_in_tag[$data['level']+1] = 0;
                    $new_tag = array('name' => $data['tag']);
                    if(isset($data['attributes']))
                    $new_tag['attributes'] = $data['attributes'];
                    if(isset($data['value']) && trim($data['value']))
                    $new_tag['value'] = trim($data['value']);
                    $last_tag_ar[$last_counter_in_tag[$data['level']]] = $new_tag;
                    $parents[$data['level']] =& $last_tag_ar;
                    $last_tag_ar =& $last_tag_ar[$last_counter_in_tag[$data['level']]++];
                    break;
                case 'complete':
                    $new_tag = array('name' => $data['tag']);
                    if(isset($data['attributes']))
                    $new_tag['attributes'] = $data['attributes'];
                    if(isset($data['value']) && trim($data['value']))
                    $new_tag['value'] = trim($data['value']);

                    $last_count = count($last_tag_ar)-1;
                    $last_tag_ar[$last_counter_in_tag[$data['level']]++] = $new_tag;
                    break;
                case 'close':
                    $last_tag_ar =& $parents[$data['level']];
                    break;
                default:
                    break;
            };
        }
        $this->struct= $xml_array;
    }

    //
    // use this to get node of tree by path with '/' terminator
    //
    function get($__tag_path){
        $tmp_arr =$this->struct;

        $tag_path = explode('/', $__tag_path);
        foreach($tag_path as $tag_name) {
            $res = false;
            foreach($tmp_arr as $key => $node) {
                if(is_int($key) && $node['name'] == $tag_name) {
                    $tmp_arr = $node;
                    $res = true;
                    break;
                }
            }
            if(!$res)
            return false;
        }
        $elem = new PXMLElement();
        $elem->struct = $tmp_arr;
        return $elem;
    }
}

class PXMLElement{

    public $struct;

    /**
     * Returns value from a xml collection
     * name_attr has form name_val@tagname where name_val
     * is the value in "name" attribute
     *
     * @param string $name_attr (name_attr@tagname)
     * @return string
     */
    function name($name_attr){
        $fract = explode("@",$name_attr);
        foreach ($this->struct as $key=>$elem){
            //var_dump($elem['name']);
            if (is_array($elem) && $elem['name']==$fract[1])
                if ($elem['attributes']['name']==$fract[0])
                    return $elem['attributes']['value'];
        }

    }


}

